package com.simple.rpc.starter;

import com.simple.rpc.annotation.RpcService;
import com.simple.rpc.component.server.ProviderServer;
import com.simple.rpc.component.registry.Registry;
import com.simple.rpc.component.cache.RpcServiceCache;
import com.simple.rpc.config.ApplicationConfig;
import com.simple.rpc.config.ServiceConfig;
import com.simple.rpc.config.RpcSystemProperties;
import com.simple.rpc.core.RpcServiceInvoker;
import com.simple.rpc.core.RpcServiceProxyFactory;
import com.simple.rpc.component.registry.SimpleRegistry;
import com.simple.rpc.component.server.SocketProviderServer;
import com.simple.rpc.component.cache.SimpleRpcServiceCache;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * simple rpc框架启动器
 *
 * @author mhh
 * @since 2020/10/20
 */
public class SimpleRpcStarter {

    /**
     * 单例启动器
     */
    private final static SimpleRpcStarter SIMPLE_RPC_STARTER = new SimpleRpcStarter();

    /**
     * 类文件名称（全类名）
     */
    private final List<String> classFileNames = new ArrayList<>();

    /**
     * 服务缓存
     */
    private final RpcServiceCache rpcServiceCache = new SimpleRpcServiceCache();

    /**
     * 注册中心
     */
    private final Registry registry = new SimpleRegistry();

    /**
     * 服务
     */
    private final ProviderServer providerServer = new SocketProviderServer();

    /**
     * 系统配置
     */
    private ApplicationConfig applicationConfig;

    private SimpleRpcStarter() {
    }

    /**
     * 单例方式获取启动器
     *
     * @return 单例启动器
     */
    public static SimpleRpcStarter getStarter() {
        return SIMPLE_RPC_STARTER;
    }

    /**
     * 服务提供者初始化
     */
    public void providerInit() {
        RpcSystemProperties.load();
        try {
            doInitApplicationConfig();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        doScanner(RpcSystemProperties.getProperty(RpcSystemProperties.SERVICE_ROOT_PATH));
        List<Class<?>> rpcServiceClasses = doRpcServiceFilter();
        List<RpcServiceInvoker> rpcServiceInvokerList = rpcServiceClasses.stream().map(rpcServiceClass -> RpcServiceProxyFactory.getInvoker(null, rpcServiceClass)).collect(Collectors.toList());


        rpcServiceClasses.forEach(rpcServiceClass -> {
            ServiceConfig serviceConfig = new ServiceConfig();
            serviceConfig.setApplicationConfig(applicationConfig);
            serviceConfig.setServiceName(rpcServiceClass.getName());
            //添加缓存
            rpcServiceCache.addServiceCache(rpcServiceClass, RpcServiceProxyFactory.getInvoker(null, rpcServiceClass));
            //注册中心注册节点
            registry.registry(serviceConfig);
        });
        //打开监听
        providerServer.listen(applicationConfig);
    }

    /**
     * 初始化系统配置
     */
    private void doInitApplicationConfig() throws UnknownHostException {
        String simpleRpcHost = RpcSystemProperties.getProperty("simpleRpcHost");
        if (StringUtils.isEmpty(simpleRpcHost)) {
            InetAddress localHost = InetAddress.getLocalHost();
            simpleRpcHost = localHost.getHostAddress();
        }
        String simpleRpcPort = RpcSystemProperties.getProperty("simpleRpcPort");
        if (StringUtils.isEmpty(simpleRpcPort)) {
            simpleRpcPort = "20880";
        }
        applicationConfig = new ApplicationConfig(simpleRpcHost, simpleRpcPort);
    }


    /**
     * 过滤出要发布的服务
     */
    private List<Class<?>> doRpcServiceFilter() {
        return classFileNames.stream().map(classFileName -> {
            try {
                return Class.forName(classFileName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return null;
            }
        }).filter(clazz -> clazz != null && clazz.isAnnotationPresent(RpcService.class)).collect(Collectors.toList());
    }

    /**
     * 根据指定的根目录扫描服务提供者
     *
     * @param serviceRootPath 服务根路径
     */
    private void doScanner(String serviceRootPath) {
        URL resource = this.getClass().getResource("/" + serviceRootPath.replaceAll("\\.", "/"));
        if (resource == null) {
            return;
        }
        File baseFile = new File(resource.getFile());
        if (baseFile.exists()) {
            File[] files = baseFile.listFiles();
            for (File file : files) {
                String name = file.getName();
                //只处理文件夹和class文件
                if (file.isDirectory()) {
                    //递归文件夹
                    doScanner(serviceRootPath + "." + name);
                } else if (name.endsWith(".class")) {
                    //把name变成全类名
                    name = (serviceRootPath + "." + name).replaceAll("\\.class", "");
                    classFileNames.add(name);
                }
            }
        }
    }

    /**
     * 服务消费者初始化
     */
    public void consumerInit() {

    }
}
